package server

import (
	"context"
	"errors"
	"fmt"
	"math/rand"
	"seckill-srv/basic/config"
	__ "seckill-srv/basic/proto"
	"seckill-srv/handler/model"
	"seckill-srv/mq/pub"
	"seckill-srv/pkg"
	"seckill-srv/untils"
	"strconv"
	"time"
)

// server is used to implement helloworld.GreeterServer.
type Server struct {
	__.UnimplementedSeckillServer
}

func (s *Server) SendSms(_ context.Context, in *__.SendSmsReq) (*__.SendSmsResp, error) {

	i := rand.Intn(9000) + 1000
	err, _ := pkg.SendSms(in.Mobile, strconv.Itoa(i))
	if err != nil {
		return nil, err
	}
	config.Rdb.Set(config.Ctx, in.Mobile+"sendSms", i, time.Minute*3)
	return &__.SendSmsResp{}, nil
}
func (s *Server) LoginUser(_ context.Context, in *__.LoginUserReq) (*__.LoginUserResp, error) {

	var user model.User
	//get, _ := config.Rdb.Get(config.Ctx, in.Mobile+"sendSms").Int64()
	//if get != in.SmsCode {
	//	return nil, errors.New("短信发送失败")
	//}
	if err := user.GetUserByMobile(in.Mobile); err != nil {
		return nil, errors.New("获取用户信息失败")
	}
	if user.ID == 0 {
		return nil, errors.New("用户不存在")
	}
	if user.Password != in.Password {
		return nil, errors.New("密码错误")
	}
	return &__.LoginUserResp{
		UserId: int64(user.ID),
	}, nil
}

// 秒杀商品添加
func (s *Server) AddActivityGoods(_ context.Context, in *__.AddActivityGoodsReq) (*__.AddActivityGoodsResp, error) {
	var err error
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	if err = tx.Error; err != nil {
		return nil, err
	}
	var goods model.Goods
	if err = goods.GetGoodsById(int(in.GoodsId)); err != nil {
		return nil, errors.New("添加商品失败")
	}

	if goods.ID == 0 {
		return nil, errors.New("该商品不存在")
	}

	//判断库存
	if goods.Stock < int(in.ActivityStock) {
		return nil, errors.New("库存不足")
	}

	//解析时间
	startTime, err := time.Parse(time.DateTime, in.StartTime)
	if err != nil {
		return nil, errors.New("开始时间解析失败" + err.Error())
	}
	endTime, err := time.Parse(time.DateTime, in.EndTime)
	if err != nil {
		return nil, errors.New("结束时间解析失败" + err.Error())
	}

	var activity model.Activity
	activity = model.Activity{
		GoodsId:           int(in.GoodsId),
		ActivityTitle:     in.ActivityTitle,
		ActivityDesc:      in.ActivityDesc,
		ActivityPrice:     float64(in.ActivityPrice),
		ActivityStock:     int(in.ActivityStock),
		ActivityStartTime: startTime,
		ActivityEndTime:   endTime,
	}
	if err = activity.AddActivity(tx); err != nil {
		tx.Rollback()
		return nil, errors.New("添加活动失败")
	}

	//redis 同步库存
	if err = untils.SyncActivityStock(int(activity.ID), activity.ActivityStock); err != nil {
		tx.Rollback()
		return nil, errors.New("同步活动库存失败")
	}
	//扣减商品库存
	goods.Stock -= int(in.ActivityStock)
	if err = goods.UpdateGoodsStock(tx, int(in.GoodsId), goods.Stock); err != nil {
		tx.Rollback()
		return nil, errors.New("商品库存扣减失败")
	}
	//修改活动状态
	activity.ActivityStatus = 2
	if err = activity.UpdateActivityStatus(tx, int(activity.ID)); err != nil {
		tx.Rollback()
		return nil, errors.New("修改活动状态失败")
	}

	if err = tx.Commit().Error; err != nil {
		return nil, err
	}

	//添加分布式锁
	if activity.ActivityStartTime.Before(time.Now()) {
		return nil, errors.New("秒杀开始时间已开始，不能添加秒杀商品")
	}

	if !untils.AddLock(int(activity.ID), activity.ActivityStartTime) {
		return nil, errors.New("添加锁失败")
	}

	return &__.AddActivityGoodsResp{
		ActivityId: int64(activity.ID),
	}, nil
}

// 创建秒杀订单
func (s *Server) CreateActivityOrder(_ context.Context, in *__.CreateActivityOrderReq) (*__.CreateActivityOrderResp, error) {
	var err error
	var user model.User
	if err = user.GetUserById(int(in.UserId)); err != nil {
		return nil, errors.New("用户信息查询失败")
	}
	if user.ID == 0 {
		return nil, errors.New("该用户不存在")
	}
	var activity model.Activity
	if err = activity.GetActivityById(int(in.ActivityId)); err != nil {
		return nil, errors.New("活动信息查询失败")
	}
	if activity.ID == 0 {
		return nil, errors.New("该活动不存在")
	}
	if activity.ActivityStatus != 2 {
		return nil, errors.New("活动已结束")
	}
	t := time.Now()
	if t.Before(activity.ActivityStartTime) {
		return nil, errors.New("活动时间未到")
	}
	if t.After(activity.ActivityEndTime) {
		return nil, errors.New("活动已结束")
	}
	stock := untils.GetActivityStock(int(activity.ID))
	if stock <= 0 {
		return nil, errors.New("活动库存不足")
	}

	if stock < int(in.OrderNum) {
		return nil, errors.New("活动库存不足")
	}
	//上锁
	if !untils.AddUserLock(int(in.UserId)) {
		return nil, errors.New("添加锁失败")
	}
	if !untils.DeleteActivityStock(int(activity.ID), int(in.OrderNum)) {
		return nil, errors.New("扣减活动库存失败")
	}
	//释放锁
	untils.DeleteUserLock(int(in.UserId))
	order := model.Order{
		UserId:          int(in.UserId),
		ActivityId:      int(in.ActivityId),
		OrderSn:         "HZ" + time.Now().Format("20060102150405") + strconv.Itoa(int(in.UserId)),
		OrderPrice:      float32(activity.ActivityPrice),
		OrderNum:        int(in.OrderNum),
		OrderStatus:     1,
		PayDurationTime: int(time.Now().Add(10 * time.Minute).Unix()), //10分钟超时
		PayStatus:       1,
	}
	if err = pub.PublishOrder(&order); err != nil {
		return nil, errors.New("发送订单信息失败")
	}
	payUrl := untils.Alipay{}
	return &__.CreateActivityOrderResp{
		OrderSn:    order.OrderSn,
		OrderPrice: float32(activity.ActivityPrice),
		PayUrl:     payUrl.ALiPay(order.OrderSn, fmt.Sprintf("%.2f", activity.ActivityPrice)),
	}, nil
}

// 修改订单状态
func (s *Server) UpdateOrderStatus(_ context.Context, in *__.UpdateOrderStatusReq) (*__.UpdateOrderStatusResp, error) {
	var err error

	//添加事务
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err = tx.Error; err != nil {
		return nil, err
	}

	//查询订单信息
	var order model.Order
	if err = order.GetOrderBySn(in.OrderSn); err != nil {
		tx.Rollback()
		return nil, errors.New("订单信息查询失败")
	}

	if order.ID == 0 {
		tx.Rollback()
		return nil, errors.New("订单不存在")
	}

	//修改订单状态
	order.PayStatus = int(in.PayStatus)
	order.PayTime = time.Now()
	if err = order.UpdateOrderStatus(tx, in.OrderSn); err != nil {
		tx.Rollback()
		return nil, errors.New("修改订单状态失败")
	}

	//查询活动信息
	var activity model.Activity
	if err = activity.GetActivityById(order.ActivityId); err != nil {
		tx.Rollback()
		return nil, errors.New("活动信息查询失败")
	}

	//判断订单状态
	if in.PayStatus == 2 {
		//扣减活动库存
		activity.ActivityStock -= order.OrderNum
		activity.ID = uint(order.ActivityId)
		if err = activity.UpdateActivityStatus(tx, int(activity.ID)); err != nil {
			tx.Rollback()
			return nil, err
		}
	} else {
		//回滚活动库存
		if !untils.ReturnActivityStock(order.ActivityId, order.OrderNum) {
			tx.Rollback()
			return nil, errors.New("回滚活动库存失败")
		}

	}

	//提交事务
	if err = tx.Commit().Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	return &__.UpdateOrderStatusResp{
		OrderSn:   order.OrderSn,
		PayStatus: int32(order.PayStatus),
	}, nil
}
